#include <iostream>
#include <memory>
#include <vector>

#include "HttpServer.hpp"
#include "Util.hpp"
#include "err.hpp"

using namespace std;
using namespace ns_server;

const string SEP = "\r\n";
const string WebRoot = "./wwwroot";
const string defaultHome = "home.html";
const string err_404 = "wwwroot/err_404.html";

class HttpRequest
{
public:
    HttpRequest() : _path(WebRoot)
    {
    }
    void Print()
    {
        logMessage(Debug, "method: %s, url: %s  version: %s",
                   _method.c_str(), _url.c_str(), _version.c_str());
        logMessage(Debug, "path: %s", _path.c_str());
        logMessage(Debug, "suffix_: %s", _suffix.c_str());
    }

public:
    string _method;       // 方法
    string _url;          // URL
    string _version;      // 版本
    vector<string> _body; // 请求行以外的东西
    string _path;         // 访问路径
    string _suffix;       // 后缀
};

// 提取请求头的内容
HttpRequest Deserialize(string &message)
{
    HttpRequest req;
    std::string line = Util::ReadOneLine(SEP, message);
    Util::ParseRequestLine(line, &req._method, &req._url, &req._version);
    while (!message.empty())
    {
        line = Util::ReadOneLine(SEP, message);
        req._body.push_back(line);
    }

    // 拼接路径
    req._path += req._url;
    if (req._path[req._path.size() - 1] == '/')
        req._path += defaultHome;
    // 获取后缀
    auto pos = req._path.rfind(".");
    if (pos == string::npos)
        req._suffix = ".html";
    else
        req._suffix = req._path.substr(pos);

    return req;
}

// 获取资源类型
string GetType(const string &suffix)
{
    if (suffix == ".html" || suffix == ".htm")
        return "text/html";
    else if (suffix == ".css")
        return "text/css";
    else if (suffix == ".js")
        return "application/x-javascript";
    else if (suffix == ".png")
        return "image/png";
    else if (suffix == ".jpg")
        return "image/jpeg";
}

// 业务处理函数
string HandlerHttp(string &message)
{
    cout << "------------------------------------" << endl;
    
    HttpRequest req = Deserialize(message);
    req.Print();
    string responce;
    string body;
    if (Util::ReadFile(req._path, &body))
    {
        // 是有的文件
        responce += "HTTP/1.0 200 OK" + SEP; // 状态行
        responce += "Content-length: " + to_string(body.size()) + SEP;
        responce += "Content-type: " + GetType(req._suffix) + SEP;
        responce += SEP;  // 空行
        responce += body; // 有效载荷
    }
    else
    {
        // 不存在的文件
        responce += "HTTP/1.0 404 Not Found" + SEP; // 状态行
        Util::ReadFile(err_404, &body);
        responce += "Content-length: " + to_string(body.size()) + SEP;
        responce += "Content-type: " + GetType(".html") + SEP;
        responce += SEP;  // 空行
        responce += body; // 有效载荷
    }

    return responce;
}

static void usage(char *argv)
{
    cout << "Usage:\n\t" << argv << endl;
}

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        usage(argv[0]);
        exit(USAGE_ERR);
    }
    uint16_t port = atoi(argv[1]);

    unique_ptr<HttpServer> usvr(new HttpServer(HandlerHttp, port));
    usvr->InitServer();
    usvr->Start();

    return 0;
}